#ifndef MAPEXTRACTOR_H
#define MAPEXTRACTOR_H


#include <QtCore/QtCore>


class MapExtractor : public QThread
{
    Q_OBJECT

    enum GameType
    {
        GAME_UNKNOWN = 0,
        GAME_XY2,           // 大话西游2
        GAME_XY3,           // 大话西游3
        GAME_XYQ,           // 梦幻西游
        GAME_XYW,           // 大话外传
        MAX_GAME_TYPE
    };

    struct MaskHeader
    {
        int     x;
        int     y;
        int     w;
        int     h;
    };

public:
    MapExtractor(QObject *parent = 0);
    virtual ~MapExtractor();

    /**
     * @brief 运行提取工作
     * @param inputPath : 游戏安装路径
     * @param outputPath : 提取出来文件存放路径
     * @param async : 是否异步提取
     * @return 调用成功返回true
     */
    bool run(const QString &inputPath, const QString &outputPath, const QString &imagePath, bool async = true);

    /**
     * @brief 停止执行提取工作，run是异步提取时才有效
     */
    void stop();

protected:
    // 提取
    bool extract();

    // 提取游戏类型
    int extractGameType();

    // 提取所有大话西游2地图
    bool extractXY2Map();
    // 提取所有大话西游3地图
    bool extractXY3Map();
    // 提取所有梦幻西游地图
    bool extractXYQMap();
    // 提取所有大话外传地图
    bool extractXYWMap();

    // 提取单个地图文件
    bool extractOneMap(const QString &filePath);

    // 提取MAPX格式地图文件
    bool extractMapInMAPX(const char *data, qint64 size);
    // 提取M1.0格式地图文件
    bool extractMapInM1_0(const char *data, qint64 size);
    // 提取M2.5格式地图文件
    bool extractMapInM2_5(const char *data, qint64 size);
    // 提取M3.0格式地图文件
    bool extractMapInM3_0(const char *data, qint64 size);
    // 提取ROL格式地图背景文件
    bool extractMapInROL0(const char *data, qint64 size);

    // 提取JPGH单元数据
    bool extractJPGH(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取地图块数据
    bool extractUnitData(const char *data, qint64 size);
    // 提取IMAG单元数据
    bool extractImageData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取MSK2单元数据
    bool extractMask2Data(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取MASK单元数据
    bool extractMaskData(const char *srcData, qint64 srcSize, int maskIndex);
    // 提取JPEG单元数据
    bool extractJPEGData(const char *srcData, qint64 srcSize);
    // 提取BLOK单元数据
    bool extractBlockData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取CELL单元数据
    bool extractCellData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取BRIG单元数据
    bool extractBrightData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取LIGT单元数据
    bool extractLightData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);
    // 提取END单元数据
    bool extractEndData(const char *srcData, qint64 srcSize, char *&dstData, qint64 &dstSize);

    // 转换风云jpeg格式到标准格式
    bool extractStandardJPEGData(const uchar *srcData, qint64 srcSize, uchar *&dstData, qint64 &dstSize);

    bool extractMaskImage(const char *srcData, qint64 srcSize, int maskIndex, const MaskHeader &header);

    void swapByte(ushort &value);

    bool fillBitmap(const ushort *data, int width, int height, int pitch);

    bool saveImageToFile();

    bool loadXY2Image();

    void removeMaskInfoFile();

    // 通知提取开始，参数是总体进度绝对数值
    void notifyStarted(int total);
    // 通知当前进度，参数是相对总体进度的绝对数值
    void notifyProgress(int pos);
    // 通知当前进度详情描述
    void notifyDetail(const QString &text);
    // 通知已经提取完成
    void notifyCompleted(bool finished, int errorCode, const QString &errorDesc);

protected:  // from QThread
    virtual void run();

signals:
    void started(int);
    void progress(int);
    void detail(const QString &);
    void completed(bool, int, const QString &);

private:
    QString mInputPath;         // 游戏目录
    QString mOutputPath;        // 输出目录
    QString mImagePath;         // 大话西游2已经解出来的地图目录

    QString mFileName;          // 当前提取地图文件名

    bool    mTerminate;

    uint    mMapType;
    int     mGameType;

    int     mMapWidth;
    int     mMapHeight;
    int     mSubMapWidth;
    int     mSubMapHeight;
    int     mSubMapRows;
    int     mSubMapCols;
    int     mSubMapCount;

    int     mCurUnitIndex;

    char    *mJpgHeader;
    qint64  mJpgHeaderSize;

    uchar  *mBmpData;
};


#endif // MAPEXTRACTOR_H
